import json
import time
import datetime
import traceback

import requests
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
from django.conf import settings


class AliyunOfflineSTT:
    def __init__(self):
        self.app_key = settings.ALIYUN_TINGWU_CONFIG["APP_KEY"]
        self.region = settings.ALIYUN_TINGWU_CONFIG["REGION"]
        self.ak = settings.ALIYUN_TINGWU_CONFIG["ACCESS_KEY_ID"]
        self.sk = settings.ALIYUN_TINGWU_CONFIG["ACCESS_KEY_SECRET"]
        self.task_id = None

    def create_task(self, file_url: str) -> str:
        print(f"开始创建任务 | 文件URL: {file_url}")

        try:
            client = AcsClient(self.ak, self.sk, self.region)
            req = CommonRequest()
            req.set_accept_format("JSON")

            # 使用公网域名（非VPC）
            req.set_domain(f"tingwu.{self.region}.aliyuncs.com")

            req.set_version("2023-09-30")
            req.set_protocol_type("https")
            req.set_method("PUT")
            req.set_uri_pattern("/openapi/tingwu/v2/tasks")
            req.add_query_param("type", "offline")

            # 设置更长的超时时间
            req.set_connect_timeout(15)  # 连接超时15秒
            req.set_read_timeout(30)  # 读取超时30秒

            task_key = "task" + datetime.datetime.now().strftime('%Y%m%d%H%M%S')
            body = {
                "AppKey": self.app_key,
                "Type": "offline",
                "Input": {
                    "SourceLanguage": "cn",
                    "FileUrl": file_url,
                    "TaskKey": task_key
                },
                "Parameters": {}
            }

            req.set_content(json.dumps(body))
            req.add_header("Content-Type", "application/json")

            print("正在发送请求...")
            resp = client.do_action_with_exception(req)
            resp_data = json.loads(resp)

            if "Data" not in resp_data:
                raise ValueError(f"响应中缺少Data字段: {resp_data}")

            self.task_id = resp_data["Data"]["TaskId"]
            print(f"任务创建成功 | TaskID: {self.task_id}")
            return self.task_id

        except Exception as e:
            error_msg = f"""
            !!! 创建任务失败 !!!
            异常类型: {type(e).__name__}
            异常信息: {str(e)}
            堆栈跟踪:
            {traceback.format_exc()}
            """
            print(error_msg)
            raise RuntimeError("创建任务失败") from e

    def get_result(self, poll_interval: float = 5.0, timeout: float = 600.0) -> dict:
        assert self.task_id, "请先调用 create_task"

        try:
            client = AcsClient(self.ak, self.sk, self.region)
            req = CommonRequest()
            req.set_accept_format("JSON")
            req.set_domain(f"tingwu.{self.region}.aliyuncs.com")
            req.set_version("2023-09-30")
            req.set_protocol_type("https")
            req.set_method("GET")
            req.set_uri_pattern(f"/openapi/tingwu/v2/tasks/{self.task_id}")
            req.add_query_param("Type", "offline")
            req.set_connect_timeout(15)
            req.set_read_timeout(30)

            elapsed = 0.0
            while elapsed < timeout:
                print(f"正在查询任务状态 | TaskID: {self.task_id}")
                resp = client.do_action_with_exception(req)
                resp_data = json.loads(resp)

                # 调试输出
                print(f"响应数据: {json.dumps(resp_data, indent=2)}")

                if "Data" not in resp_data:
                    raise ValueError(f"无效响应: {resp_data}")

                data = resp_data.get("Data", {})
                task_status = data.get("TaskStatus")  # 关键修改：使用正确的字段名

                # 任务状态判断
                if task_status == "COMPLETED":
                    result_url = data.get("Result", {}).get("Transcription")
                    if not result_url:
                        raise ValueError("结果URL缺失")

                    # 下载结果文件
                    print(f"下载转写结果: {result_url}")
                    response = requests.get(result_url)
                    if response.status_code != 200:
                        raise RuntimeError(f"下载失败: {response.status_code}")

                    return response.json()

                elif task_status == "FAILED":
                    raise RuntimeError(f"任务失败: {data}")

                elif task_status == "ONGOING":
                    print(f"任务处理中 | 耗时: {elapsed:.1f}s")
                    time.sleep(poll_interval)
                    elapsed += poll_interval
                    continue

                else:
                    raise RuntimeError(f"未知状态: {task_status}")

            raise TimeoutError("离线转写轮询超时")

        except Exception as e:
            error_msg = f"""
            !!! 获取结果失败 !!!
            异常类型: {type(e).__name__}
            异常信息: {str(e)}
            堆栈跟踪:
            {traceback.format_exc()}
            """
            print(error_msg)
            raise